﻿using System;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    using static OpenStateType;
    using static StoryPlaySpeedType;

    public class SettingModuleData : IReusableClass
    {
        #region Game
        public SettingGameData gameData { get; private set; } = SettingGameData.Default;
        private PlayerPreferenceString playerPrefsGameData = new PlayerPreferenceString(PlayerPrefsConst.SettingGame,String.Empty);
        private int targetFrameRate => gameData.highFrame == Open ? 60 : 30;
        public bool isAutoPlayStory => gameData.storyAutoPlay == Open;
        public bool isUseDefaultNameInStory => gameData.storyDefaultName == Open;
        public int storyPlaySpeed
        {
            get
            {
                return gameData.storyPlaySpeed switch
                {
                    Fast => 2,
                    FastMore => 4,
                    _ => 1
                };
            }
        }
        #endregion Game

        #region Audio
        public SettingAudioData audioData { get; private set; } = SettingAudioData.Default;
        private PlayerPreferenceString playerPrefsAudioData = new PlayerPreferenceString(PlayerPrefsConst.SettingAudio,String.Empty);
        #endregion Auido

        public void Initialize()
        {
            InitializeGameData();
            InitializeAudioData();
            OnInitialize();
        }

        private void InitializeGameData()
        {
            if (!string.IsNullOrEmpty(playerPrefsGameData.Value))
                gameData = JsonHelper.DeserializeJson<SettingGameData>(playerPrefsGameData.Value);
        }
        

        private void InitializeAudioData()
        {
            if (!string.IsNullOrEmpty(playerPrefsAudioData.Value))
                audioData = JsonHelper.DeserializeJson<SettingAudioData>(playerPrefsAudioData.Value);
        }

        private void OnInitialize()
        {
            ResetGameData();
            ResetAudioData();
        }

        private void ResetGameData()
        {
            Application.targetFrameRate = targetFrameRate;
            ManagerCenter.Render.SetLODLevel((int)gameData.quality);
        }

        private void ResetAudioData()
        {
            SetVolume(AudioVolumeType.Bgm, audioData.bgm);
            SetVolume(AudioVolumeType.Sfx, audioData.sfx);
            SetVolume(AudioVolumeType.Voice, audioData.voice);
        }

        private void SetVolume(AudioVolumeType type, int value)
        {
            ManagerCenter.Audio.SetVolume(type, Mathf.Clamp01(value / 100.0f));
        }

        public void SaveGameData(SettingGameData data)
        {
            bool isChanged = this.gameData != data;
            if (isChanged)
            {
                this.gameData = data;
                SaveGameJsonData();
                ResetGameData();
            }
        }

        private void SaveGameJsonData()
        {
            playerPrefsGameData.Value = JsonHelper.SerializeObject(gameData);
        }

        public void SetStoryIsAutoPlay(bool isAutoPlay)
        {
            var data = this.gameData;
            data.storyAutoPlay = isAutoPlay ? Open : Close;
            SaveGameData(data);
        }

        public void SetStoryAutoSpeed(int speed)
        {
            int current = Math.Clamp(speed, 1, 4);
            var data = this.gameData;
            data.storyPlaySpeed = (current == 1) ? Normal : (current == 2) ? Fast : FastMore;
            SaveGameData(data);
        }
        
        public void SaveAudioData(SettingAudioData data)
        {
            bool isChanged = this.audioData != data;
            if (isChanged)
            {
                this.audioData = data;
                SaveAudioJsonData();
                ResetAudioData();
            }
        }

        private void SaveAudioJsonData()
        {
            playerPrefsAudioData.Value = JsonHelper.SerializeObject(audioData);
        }

        private void OnReset()
        {
            gameData = SettingGameData.Default;
            audioData = SettingAudioData.Default;
        }

        #region 对象池
        uint IReusableClass.MaxStore => 1;

        void IReusableClass.OnReset()
        {
            this.OnReset();
        }

        public void Put2Pool()
        {
            ClassPool.PutAutoType(this);
        }

        static public SettingModuleData NewFromPool()
        {
            return ClassPool<SettingModuleData>.Get();
        }
        #endregion

    }
}
